<?php

/**
 * This file is part of Webman AI.
 *
 * @author    walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link      http://www.workerman.net/
 */

namespace plugin\ai\app\service;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use plugin\ai\app\model\AiModel;
use Random\RandomException;
use support\exception\BusinessException;

class Common
{

    /**
     * 获取模型处理器
     * @param $model
     * @return string|null
     */
    public static function getModelHandler($model): ?string
    {
        if (!$item = static::getModelInfo($model)) {
            return null;
        }
        if (class_exists($handler = (string)$item->handler)) {
            return $handler;
        }
        return null;
    }

    /**
     * 获取模型信息
     * @param $model
     * @return AiModel
     */
    public static function getModelInfo($model)
    {
        foreach (static::getModelItems() as $item) {
            if (in_array($model, $item->models)) {
                $handler = (string)$item->handler;
                if (class_exists($handler)) {
                    return $item;
                }
            }
        }
        return null;
    }

    /**
     * 获取模型信息
     * @param $modelType
     * @return Builder|\Illuminate\Database\Eloquent\Model|object
     */
    public static function getModelInfoByType($modelType)
    {
        return AiModel::where('type', $modelType)->orderBy('priority')->first();
    }

    /**
     * 获取所有模型信息
     * @return array|Builder[]|Collection
     */
    public static function getModelItems()
    {
        static $items = [], $lastTime = 0;
        if (time() - $lastTime > 1) {
            $items = AiModel::where('status', 0)->orderBy('priority', 'desc')->get();
            if ($items->isEmpty()) {
                AiModel::init();
                $items = AiModel::where('status', 0)->orderBy('priority', 'desc')->get();
            }
            $lastTime = time();
        }
        return $items;
    }

    /**
     * 获取所有支持的模型
     * @return array
     */
    public static function getModels(): array
    {
        $models = [];
        $items = static::getModelItems();
        foreach ($items as $item) {
            $models = array_merge($models, $item->models);
        }
        return $models;
    }

    /**
     * 获取模型类型列表
     * @param bool $balanceVisible
     * @return array
     */
    public static function getModelTypes(bool $balanceVisible = false): array
    {
        $enabledModelTypes = [];
        $availableModelTypes = Common::getModelItems();
        foreach ($availableModelTypes as $item) {
            if ($balanceVisible && !$item->balance_visible) {
                continue;
            }
            $enabledModelTypes[$item->type] = $item['name'];
        }
        ksort($enabledModelTypes);
        return $enabledModelTypes;
    }

    /**
     * 获取模型每天免费次数
     * @param $model
     * @return int|mixed
     * @throws BusinessException
     */
    public static function getDayFreeCount($model)
    {
        $modelItem = static::getModelInfo($model);
        if (!$modelItem) {
            throw new BusinessException("模型 $model 没有对应的处理器");
        }
        return $modelItem->settings['dayFreeCount']['value'] ?? 0;
    }

    /**
     * 获取模型类型
     * @param $model
     * @return string
     */
    public static function getModelType($model): string
    {
        if ($modelItem = static::getModelInfo($model)) {
            return $modelItem->type;
        }
        $modelTypes = [
            'gpt-3' => 'gpt3',
            'gpt-4' => 'gpt4',
            'dall' => 'dalle',
            'glm' => 'chatglm',
        ];
        foreach($modelTypes as $prefix => $type) {
            if (strpos($model, $prefix) === 0) {
                return $type;
            }
        }
        return explode('-', $model)[0];
    }

    /**
     * @return string
     * @throws RandomException
     */
    public static function uniqId(): string
    {
        $string = str_replace('.', '', (string)microtime(true));
        return substr($string, 0, 13) . random_int(100000, 999999);
    }

    public static function urlToFile($url)
    {
        $path = parse_url($url, PHP_URL_PATH);
        if (!$path) {
            return false;
        }
        if (strpos($path, '..') !== false) {
            return false;
        }
        $prefix = '/app/ai/';
        if (strpos($path, $prefix) === 0) {
            $path = substr($path, strlen($prefix));
            $file = base_path('plugin/ai/public/' . $path);
        } else {
            $file = public_path($path);
        }
        if (!is_file($file)) {
            return false;
        }
        return $file;
    }

}